<?php

namespace app;

use app\admin\model\Client;
use app\admin\model\ClientObserver;
use app\admin\model\Site;
use app\admin\model\SiteObserver;
use app\admin\services\client\ClientServices;
use app\admin\services\download\DownloaderServices;
use Ledc\Element\Concrete;
use Ledc\Element\GenerateInterface;
use plugin\cron\api\CrontabExtend;
use plugin\cron\app\interfaces\CrontabLayuiTemplateInterface;
use plugin\cron\app\interfaces\CrontabSchedulerInterface;
use plugin\cron\app\interfaces\CrontabTaskTypeEnumsInterface;
use plugin\cron\app\services\CrontabRocket;
use Workerman\Crontab\Crontab;
use Workerman\Worker;

/**
 * 进程启动时onWorkerStart时运行的回调配置
 * @link https://learnku.com/articles/6657/model-events-and-observer-in-laravel
 */
class Bootstrap implements \Webman\Bootstrap
{
    /**
     * @param Worker|null $worker
     * @return void
     */
    public static function start(?Worker $worker): void
    {
        self::initObserver();

        ClientServices::bootstrap();
        DownloaderServices::bootstrap();
    }

    /**
     * 初始化模型观察者
     * @return void
     */
    protected static function initObserver(): void
    {
        //【新增】依次触发的顺序是：
        //saving -> creating -> created -> saved

        //【更新】依次触发的顺序是:
        //saving -> updating -> updated -> saved

        // updating 和 updated 会在数据库中的真值修改前后触发。
        // saving 和 saved 则会在 Eloquent 实例的 original 数组真值更改前后触发
        Client::observe(ClientObserver::class);
        Site::observe(SiteObserver::class);

        // 示例：扩展支持一个新的计划任务类型
        CrontabExtend::getInstance()->registerEnumsProvider(new class implements CrontabTaskTypeEnumsInterface {
            public static function select(): array
            {
                return [
                    '自动下载' => 50,
                    '自动转移' => 51,
                ];
            }
        })->registerTemplateProvider(new class implements CrontabLayuiTemplateInterface {
            public function generate(int $type): ?GenerateInterface
            {
                return match ($type) {
                    50, 51 => new Concrete(),
                    default => null,
                };
            }
        })->registerSchedulerProvider(new class implements CrontabSchedulerInterface {
            public function start(CrontabRocket $rocket): ?Crontab
            {
                $model = $rocket->model;
                return match ((int)$model->task_type) {
                    50, 51 => new Crontab($model->rule, function () use ($rocket) {
                        $exception = '任务执行成功，任务ID：' . $rocket->model->crontab_id . PHP_EOL;
                        send_shell_output($rocket->model->crontab_id, $exception);
                        $rocket->model->updateRunning(time());
                    }),
                    default => null,
                };
            }
        });
    }
}
